//
//  EAGLView.m
//  iphonetest
//
//  Created by omega on 08/12/13.
//  Copyright __MyCompanyName__ 2008. All rights reserved.
//



#import <QuartzCore/QuartzCore.h>
#import <OpenGLES/EAGLDrawable.h>

#import "EAGLView.h"
#import "hellApp.h"

#import "string.h"
#import "SoundEngine.h"

#define USE_DEPTH_BUFFER			0
#define kListenerDistance			1.0  // Used for creating a realistic sound field

// A class extension to declare private methods
@interface EAGLView ()

@property (nonatomic, retain) EAGLContext *context;
@property (nonatomic, assign) NSTimer *animationTimer;

- (BOOL) createFramebuffer;
- (void) destroyFramebuffer;
- (void) drawFontWithTexture:(Texture2D*)texture cstring:(char*)str;
@end


@implementation EAGLView

@synthesize context;
@synthesize animationTimer;
@synthesize animationInterval;


// You must implement this method
+ (Class)layerClass {
    return [CAEAGLLayer class];
}


//The GL view is stored in the nib file. When it's unarchived it's sent -initWithCoder:
- (id)initWithCoder:(NSCoder*)coder {
    if ((self = [super initWithCoder:coder])) {
        // Get the layer
        CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
        
        eaglLayer.opaque = YES;
        eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                        [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
        
        context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
        
        if (!context || ![EAGLContext setCurrentContext:context]) {
            [self release];
            return nil;
        }
		
		_accelerate.x = _accelerate.y = _accelerate.z = 0;
        animationInterval = HELL_FRAME_INTERVAL;
		[self setMultipleTouchEnabled:YES];
    }
    return self;
}


- (void)drawView {
    [EAGLContext setCurrentContext:context];
    
	glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    glViewport(0, 0, backingWidth, backingHeight);
    
	Hell_update();
	Hell_draw();
	
	glDisable(GL_BLEND);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context presentRenderbuffer:GL_RENDERBUFFER_OES];
}


- (void)layoutSubviews {
    [EAGLContext setCurrentContext:context];
    [self destroyFramebuffer];
    [self createFramebuffer];
    [self drawView];
}


- (BOOL)createFramebuffer {
    
    glGenFramebuffersOES(1, &viewFramebuffer);
    glGenRenderbuffersOES(1, &viewRenderbuffer);
    
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
    
    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
    
    if (USE_DEPTH_BUFFER) {
        glGenRenderbuffersOES(1, &depthRenderbuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
        glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
    }
    
    if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
        NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
        return NO;
    }
    
    return YES;
}


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
	Hell_TouchEvent touchevents[HELL_TOUCHEVENT_MAX];
	NSSet *alltouches = [event allTouches];
	int t = 0;
	for(UITouch *touch in alltouches) {
		CGPoint p = [touch locationInView:self];
		CGPoint prev = [touch previousLocationInView:self];
		
		touchevents[t].x		= (p.x - 160.0f);
		touchevents[t].y		= -(p.y - 240.0f);
		touchevents[t].prev_x	= (prev.x - 160.0f);
		touchevents[t].prev_y	= -(prev.y - 240.0f);
		touchevents[t].phase	= touch.phase;
		touchevents[t].tapCount	= touch.tapCount;
		
		t++;
		if( t >= HELL_TOUCHEVENT_MAX ) break;
	}
	Hell_callbackTouchBegan( touchevents , t );
}
	
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
	Hell_TouchEvent touchevents[HELL_TOUCHEVENT_MAX];
	NSSet *alltouches = [event allTouches];
	int t = 0;
	for(UITouch *touch in alltouches) {
		CGPoint p = [touch locationInView:self];
		CGPoint prev = [touch previousLocationInView:self];
		
		touchevents[t].x		= (p.x - 160.0f);
		touchevents[t].y		= -(p.y - 240.0f);
		touchevents[t].prev_x	= (prev.x - 160.0f);
		touchevents[t].prev_y	= -(prev.y - 240.0f);
		touchevents[t].phase	= touch.phase;
		touchevents[t].tapCount	= touch.tapCount;
		
		t++;
		if( t >= HELL_TOUCHEVENT_MAX ) break;
	}
	Hell_callbackTouchMoved( touchevents , t );
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
	Hell_TouchEvent touchevents[HELL_TOUCHEVENT_MAX];
	NSSet *alltouches = [event allTouches];
	int t = 0;
	for(UITouch *touch in alltouches) {
		CGPoint p = [touch locationInView:self];
		CGPoint prev = [touch previousLocationInView:self];
		
		touchevents[t].x		= (p.x - 160.0f);
		touchevents[t].y		= -(p.y - 240.0f);
		touchevents[t].prev_x	= (prev.x - 160.0f);
		touchevents[t].prev_y	= -(prev.y - 240.0f);
		touchevents[t].phase	= touch.phase;
		touchevents[t].tapCount	= touch.tapCount;
		
		t++;
		if( t >= HELL_TOUCHEVENT_MAX ) break;
	}
	Hell_callbackTouchEnded( touchevents , t );
}

- (void)drawFontWithTexture:(Texture2D*)texture cstring:(char*)str
{
	unsigned i;
	float FONTSIZE_X = 8.0f;
	float FONTSIZE_Y = 8.0f;
	unsigned COLUMN = 16;
	char* buf = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.()[]#$%&'\"!?^+-*/=;:\0";
	float x = 0.0f;
	
	for(i = 0 ; i < strlen(str) ; i++){
		char c = (char)str[i];
		char *idx = strchr(buf,c);
		if( idx != NULL ){
			int tx = ((idx - buf) % COLUMN);
			int ty = ((idx - buf) / COLUMN);
			[texture drawClipRect:CGRectMake( tx * FONTSIZE_X , ty * FONTSIZE_Y , FONTSIZE_X , FONTSIZE_Y ) DestPoint:CGPointMake( x , 0 )];
		}
		x += FONTSIZE_X;
	}
}

- (void)destroyFramebuffer {    
    glDeleteFramebuffersOES(1, &viewFramebuffer);
    viewFramebuffer = 0;
    glDeleteRenderbuffersOES(1, &viewRenderbuffer);
    viewRenderbuffer = 0;
    
    if(depthRenderbuffer) {
        glDeleteRenderbuffersOES(1, &depthRenderbuffer);
        depthRenderbuffer = 0;
    }
}


- (void)updateAccelerometerWithX:(float)x Y:(float)y Z:(float)z {
	_accelerate.x = x * HELL_ACCELEROMETER_FILTER + _accelerate.x * (1.0f - HELL_ACCELEROMETER_FILTER);
	_accelerate.y = y * HELL_ACCELEROMETER_FILTER + _accelerate.y * (1.0f - HELL_ACCELEROMETER_FILTER);
	_accelerate.z = z * HELL_ACCELEROMETER_FILTER + _accelerate.z * (1.0f - HELL_ACCELEROMETER_FILTER);
}

- (void)startAnimation {
    self.animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self selector:@selector(drawView) userInfo:nil repeats:YES];
}


- (void)stopAnimation {
    self.animationTimer = nil;
}


- (void)setAnimationTimer:(NSTimer *)newTimer {
    [animationTimer invalidate];
    animationTimer = newTimer;
}


- (void)setAnimationInterval:(NSTimeInterval)interval {
    
    animationInterval = interval;
    if (animationTimer) {
        [self stopAnimation];
        [self startAnimation];
    }
}


- (void)dealloc {
    unsigned int i;
	
    [self stopAnimation];
//	SoundEngine_Teardown();	
    if ([EAGLContext currentContext] == context) {
        [EAGLContext setCurrentContext:nil];
    }
	for(i = 0; i<HELL_TEXTURE_MAX; ++i) {
		if( _textures[i] ) [_textures[i] release];
	}
    [context release];  
    [super dealloc];
}

@end
